package org.framework.lazy.cloud.network.heartbeat.protocol.advanced;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.socksx.v5.DefaultSocks5CommandResponse;
import io.netty.handler.codec.socksx.v5.Socks5AddressType;
import io.netty.handler.codec.socksx.v5.Socks5CommandRequestDecoder;
import io.netty.handler.codec.socksx.v5.Socks5CommandStatus;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.payload.NettyChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.payload.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.payload.NettySocketChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.proxy.socks.AbstractHandleSocketLocalProxyTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.factory.EventLoopGroupFactory;
import org.framework.lazy.cloud.network.heartbeat.protocol.handler.NettyProxy2RealInboundHandler;
import org.framework.lazy.cloud.network.heartbeat.protocol.handler.NettySocketBackendHandler;
import org.framework.lazy.cloud.network.heartbeat.protocol.handler.NettySocks5CommandRequestHandler;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;

@Slf4j
@Component
public class NettySocketProtocolHandleSocketLocalProxyTypeAdvanced
        extends AbstractHandleSocketLocalProxyTypeAdvanced<NettyProxyMsg> {
    /**
     * 处理当前数据
     *
     * @param nettyChannelContext           当前通道
     * @param nettyProxyMsg 通道数据
     */
    @Override
    protected void doHandler(NettyChannelContext nettyChannelContext, NettyProxyMsg nettyProxyMsg) {
        NettySocketChannelContext nettySocketChannelContext = (NettySocketChannelContext) nettyChannelContext;
        Channel channel = nettySocketChannelContext.channel();
        ChannelHandlerContext channelHandlerContext = nettySocketChannelContext.channelHandlerContext();
        EventLoopGroup group = EventLoopGroupFactory.createClientWorkGroup();
        String host = nettyProxyMsg.getTargetIpString();
        Integer port = Integer.parseInt(nettyProxyMsg.getTargetPortString());
        Bootstrap b = new Bootstrap();
        Socks5AddressType socks5AddressType = nettySocketChannelContext.getSocks5AddressType();

        b.group(group)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new NettySocketBackendHandler(channelHandlerContext));
                    }
                });
        log.info("准备连接目标服务器，ip={},port={}", host, port);
        ChannelFuture f = b.connect(new InetSocketAddress(host, port));
        f.addListener((ChannelFutureListener) future -> {
            if (future.isSuccess()) {
                log.info("目标服务器连接成功");
                //添加客户端转发请求到服务端的Handler
                channel.pipeline().addLast(new NettyProxy2RealInboundHandler(future));
                DefaultSocks5CommandResponse commandResponse = new DefaultSocks5CommandResponse(Socks5CommandStatus.SUCCESS, socks5AddressType);
                channel.writeAndFlush(commandResponse);
                channel.pipeline().remove(NettySocks5CommandRequestHandler.class);
                channel.pipeline().remove(Socks5CommandRequestDecoder.class);
            } else {
                log.error("连接目标服务器失败,address={},port={}", host, port);
                DefaultSocks5CommandResponse commandResponse = new DefaultSocks5CommandResponse(Socks5CommandStatus.FAILURE, socks5AddressType);
                channel.writeAndFlush(commandResponse);
                future.channel().close();
            }

        });

    }
}
